
#ifndef	__KC_FEKCAB_CLIENT_HPP_2010__
#define	__KC_FEKCAB_CLIENT_HPP_2010__

#include <string>
#include <utility>
#include <vector>

#include <boost/thread/mutex.hpp>


namespace	fekcab	{
namespace	client	{

class	Broker;


struct  kv_type
{
	std::string	table;
    std::string key;
    std::string value;
    /*  
     * status code for key-value operation :
     *   100 -- NOT-FOUND for GET operation only
     *   200 -- operate (PUT/GET/ERASE) successfully
     *   400 -- DB operate (PUT/GET/ERASE) failure
     *   405 -- LUA script operate failure
     *   500 -- fatal service error
     */
    u_int32_t   status;

public	:
	kv_type( const std::string& t, const std::string& k, const std::string& v, u_int32_t s=0 ) 
			:	table(t), key(k), value(v),status(0)
	{
	}
	kv_type( const std::string& k, const std::string& v, u_int32_t s=0 ) 
			:	key(k), value(v),status(0)
	{
	}
};


class	Client
{

public	:
	Client( const char* app_config );
	Client( const char* host, int port );

	~Client();

public	:
    
	int   insert( const std::string& key,  
			      const std::string& data );

	int   insertAppend( const std::string& key,  
			            const std::string& data );

	int   insertIgnore( const std::string& key,  
			            const std::string& data );

	int   find( const std::string& key,  
			          std::string& data );

	int   find( const std::string& key,  
			          std::vector< std::string >& data,
					  u_int32_t limit = 0 );

	int   erase( const std::string& key );

public	:
    
	int   insert( const std::string& table,  
				  const std::string& key,
			      const std::string& data );

	int   insertAppend( const std::string& table,  
					    const std::string& key,
			            const std::string& data );

	int   insertIgnore( const std::string& table,  
					    const std::string& key,
			            const std::string& data );

	int   find( const std::string& table,  
				const std::string& key,
			          std::string& data );

	int   find( const std::string& table,  
				const std::string& key,
			          std::vector< std::string >& data,
					  u_int32_t limit = 0 );

	int   erase( const std::string& table,
				 const std::string& key );

public	:
	// increase and return value of key, as int64_t
	int64_t	inc( const std::string& key, int64_t delta = 1 );

	// decrease and return value of key, as int64_t
	int64_t	dec( const std::string& key, int64_t delta = 1 );

	// increase and return value of key, as int64_t
	int64_t	inc( const std::string& table, const std::string& key, int64_t delta = 1 );

	// decrease and return value of key, as int64_t
	int64_t	dec( const std::string& table, const std::string& key, int64_t delta = 1 );

private	:

	int64_t	__doIncOrDec( const std::string& table, const std::string& key, int64_t delta, int op );
	
public	:
	int   insert( const std::vector< kv_type >& kvs );  

	int   insertAppend( const std::vector< kv_type >& kvs );  

	int   insertIgnore( const std::vector< kv_type >& kvs );  

	int   find( std::vector< kv_type >& key );

	int   erase( const std::vector< std::string >& key );

    
private	:
	int	  __insert( const std::string& key,
	                const std::string& data,
					int    op );

	int	  __insert( const std::string& table,
	                const std::string& key,
	                const std::string& data,
					int    op );

	int   __insert( const std::vector< kv_type >& kvs, int op );  

private	:
	int		parseAppConfig( const char* filename );
	int		parseLogConfig( const char* filename );

	int		initialize();
	int		finalize();

	int		getSid();

private	:
	Broker*	getBroker( void );

	int		callBroker( Broker* broker_p, const std::string& request, std::string& response );

private	:
	typedef	std::string	host_type;
	typedef	std::string	port_type;
	typedef	std::pair< host_type, port_type >	server_address_type;
	typedef	std::vector< server_address_type >	server_address_list_type;
	server_address_list_type	server_address_list;
	
	typedef	std::vector< Broker* >	server_list_type;
	server_list_type	server_list;

	int		_current_sid;
	boost::mutex	_current_sid_mutex;

};	// class Client


}	// namespace client
}	// namespace fekcab

#endif	// __KC_FEKCAB_CLIENT_HPP_2010__

